﻿namespace PrismEx.UnityExtensions
{
    using System.Linq;
    using System.Reflection;

    using Microsoft.Practices.ObjectBuilder2;
    using Microsoft.Practices.Prism.Events;

    using PrismEx.Events;
    using PrismEx.Interfaces;

    public class AutoSubscribeBuilderStrategy : BuilderStrategy
    {
        private readonly IEventAggregator eventAggregator;

        public AutoSubscribeBuilderStrategy(IEventAggregator eventAggregator)
        {
            this.eventAggregator = eventAggregator;
        }

        public override void PostBuildUp(IBuilderContext context)
        {
            var type = context.Existing.GetType();
            var autoSubscriptions = type.GetInterfaces().Where(i => i.GetGenericTypeDefinition() == typeof(IAutoSubscribe<>));
            var eventTypes = autoSubscriptions.SelectMany(s => s.GetGenericArguments());

            foreach (var eventType in eventTypes)
            {
                var subscriptionDelegate = type.GetProperty("Handler", BindingFlags.Public | BindingFlags.Instance).GetValue(context.Existing, null);

                var subscribeMethod = typeof(EventAggregatorExtensions)
                .GetMethods(BindingFlags.Static | BindingFlags.Public)
                .Where(mi => mi.Name == "Subscribe" && mi.GetGenericArguments().Count() == 1).First().MakeGenericMethod(eventType);

                subscribeMethod.Invoke(eventAggregator, new object[] { eventAggregator, subscriptionDelegate });
            }
        }
    }
}
